package com.xingu.xg.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xingu.xg.mapper.TreeMapper;
import com.xingu.xg.po.Tree;
import com.xingu.xg.po.TreeU;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class TreeService {

    @Autowired
    TreeMapper treeMapper;


    //查询结构化的全部树
    public List<TreeU> queryAllByStruct() {
        //查出全部节点
        List<TreeU> result = new ArrayList<>();
        QueryWrapper<Tree> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("sequence");
        List<Tree> list = treeMapper.selectList(wrapper);

        //筛选出根节点
        for (Tree tree : list) {
            if (tree.getTier() == 1) {
                result.add(new TreeU(tree));
            }
        }
        //查出全部数据并用它结构化目标集合，使其成树
        structTreeU(list,result);
        return result;
    }


    //同级向下创建数据或向上创建数据。
    //Parameter Boolean isUp 指定向上创建还是向下创建
    //Parameter int id 选中的节点id
    public void upOrDownCreateNode(Boolean isUp, int id) {

        //查出选中的节点数据
        Tree tree = treeMapper.selectById(id);

        //待插类的数据初始化
        Tree newTree = new Tree();
        newTree.setTier(tree.getTier());
        newTree.setFather(tree.getFather());
        newTree.setChildrenCount(0);

        //查出选中节点的兄弟节点
        QueryWrapper<Tree> wrapper = new QueryWrapper<>();
        wrapper.eq("father", tree.getFather());
        List<Tree> trees = treeMapper.selectList(wrapper);

        //新节点插入时的位置后移量
        int sep = 1;
        if (isUp) sep = 0;

        //插入点的选中节点父类的孩子数量加一
        Tree father = treeMapper.selectById(tree.getFather());
        father.setChildrenCount(father.getChildrenCount()+1);
        treeMapper.updateById(father);

        //插入待插节点
        newTree.setSequence(tree.getSequence()+sep);
        treeMapper.insert(newTree);

        //更改后续兄弟节点的顺序
        for (int i = 0; i < trees.size() && trees.get(i).getSequence() >= tree.getSequence()+sep; i++) {
            QueryWrapper<Tree> uptadeWrapper = new QueryWrapper<>();
            uptadeWrapper.eq("id", trees.get(i).getId());
            trees.get(i).setSequence(trees.get(i).getSequence() + 1);
            treeMapper.update(trees.get(i), uptadeWrapper);
        }

    }

    //创建子级或创建父级。
    //Parameter Boolean isFather 指定创建父类还是创建子类
    //Parameter int id 选中的节点id
    public void createChildOrFatherNodeForSelfNode(Boolean isFather, int id){
        Tree tree = treeMapper.selectById(id);
        Tree newTree = new Tree();
        if(isFather){
            //插入要新建的父类节点
            newTree.setFather(tree.getFather());
            newTree.setSequence(tree.getSequence());
            newTree.setTier(tree.getTier());
            treeMapper.insert(newTree);

            //更改选中节点的子类，需要修改它们的层数和父类指针
            tree.setTier(tree.getTier()+1);
            tree.setFather(newTree.getId());
            treeMapper.updateById(tree);

            //递归修改选中节点子类的层级，只需修改层数
            QueryWrapper<Tree> wrapper = new QueryWrapper<>();
            wrapper.eq("father", tree.getId());
            List<Tree> list = treeMapper.selectList(wrapper);
            if (list==null) return;
            deepUpdateTreeOfTierOrFather(list,true,0);
        }
        else {
            //选中节点的孩子数量加一
            tree.setChildrenCount(tree.getChildrenCount()+1);
            treeMapper.updateById(tree);

            //插入新建的子类节点，其中先找好待插节点的序列、父类指针和层次
            int seqMax = 0;
            QueryWrapper<Tree> wrapper = new QueryWrapper<>();
            wrapper.eq("father", tree.getId());
            List<Tree> trees = treeMapper.selectList(wrapper);
            for (Tree value : trees) {
                if (seqMax < value.getSequence()) seqMax = value.getSequence();
            }
            newTree.setFather(tree.getId());
            newTree.setSequence(seqMax+1);
            newTree.setTier(tree.getTier()+1);
            treeMapper.insert(newTree);
        }
    }

    //深拷贝节点
    //Parameter int resource 指定拷贝的节点
    //Parameter int target 选中的拷贝的目标节点id
    public void deepCopyNode(int resource,int target){

        //查出目标节点的全部子节点
        QueryWrapper<Tree> wrapper = new QueryWrapper<>();
        wrapper.eq("father",target);
        List<Tree> list = treeMapper.selectList(wrapper);

        //查出目标节点的子节点的最大序号
        int seqMax= 0;
        for(int i = 0; i < list.size() && list.get(i).getSequence() > seqMax; i++){
            seqMax = list.get(i).getSequence();
        };

        //修改目标节点的孩子数量
        Tree targetTree = treeMapper.selectById(target);
        targetTree.setChildrenCount(targetTree.getChildrenCount()+1);
        treeMapper.updateById(targetTree);

        //修改源节点的数据并插入
        Tree temTree = treeMapper.selectById(resource);
        temTree.setId(0);
        temTree.setFather(target);
        temTree.setTier(targetTree.getTier()+1);
        temTree.setSequence(seqMax+1);
        treeMapper.insert(temTree);

        //递归修改源节点的孩子数据
        wrapper = new QueryWrapper<>();
        wrapper.eq("father", resource);
        List<Tree> children = treeMapper.selectList(wrapper);
        if(children != null)
            deepTreeOfTier(children,targetTree.getTier()+2,temTree.getId());
    }


    //选中数据进行安全删除（其子类不会被删）。
    //Parameter int[] ids 指定被删的节点
    public void securityDeleteNode(int id){
        Tree tree = treeMapper.selectById(id);
        if(tree == null) return;
        Tree father = treeMapper.selectById(tree.getFather());
        Tree temTree;
        //删除该节点
        treeMapper.deleteById(tree);

        QueryWrapper<Tree> wrapper = new QueryWrapper<>();
        wrapper.eq("father", tree.getFather());
        List<Tree> trees = treeMapper.selectList(wrapper);

        //规整删除结点的兄弟顺序并记录最大顺序值
        int seqMax = 1;
        for (int i = 0; i < trees.size() && trees.get(i).getSequence() >= tree.getSequence(); i++) {
            QueryWrapper<Tree> updateWrapper = new QueryWrapper<>();
            updateWrapper.eq("id", trees.get(i).getId());
            trees.get(i).setSequence(trees.get(i).getSequence() - 1);
            treeMapper.update(trees.get(i), updateWrapper);
            if(trees.get(i).getSequence() > seqMax) seqMax = trees.get(i).getSequence();
        }

        //查出删除节点的孩子节点
        wrapper = new QueryWrapper<>();
        wrapper.eq("father", id);
        List<Tree> list = treeMapper.selectList(wrapper);

        //更新删除节点父类的孩子数量
        if(father!= null) {
            father.setChildrenCount(father.getChildrenCount() - 1 + list.size());
            treeMapper.updateById(tree);
        }

        //更新删除节点的子类层级和父类指针
        deepUpdateTreeOfTierOrFather(list,false,tree.getFather());

        //将删除节点的子类父类指针设为删除节点的父类节点
        for (Tree value : list) {
            temTree = value;
            temTree.setTier(temTree.getTier() - 1);
            temTree.setSequence(seqMax++);
            temTree.setFather(tree.getFather());
            treeMapper.updateById(temTree);
        }

    }

    ////查出全部数据并用它结构化目标集合，使其成树
    public void structTreeU(List<Tree> list, List<TreeU> result){
        for (TreeU treeU : result) {
            List<TreeU> children = new ArrayList<>();
            //封装子类
            if (treeU.getChildrenCount() > 0) {
                for (Tree tree : list) {
                    if (treeU.getId() == tree.getFather())
                        children.add(new TreeU(tree));
                }
                //封装
                treeU.setChildren(children);
                //递归
                structTreeU(list, children);
            }
        }
    }

    //递归修改其层数或其父类指针
    public void deepUpdateTreeOfTierOrFather(List<Tree> list, Boolean isAddTier, int father){
        Tree tree;
        for (Tree value : list) {

            //修改层数和父类指针
            tree = new Tree();
            tree.setId(value.getId());
            tree.setSequence(value.getSequence());
            if (father == 0)
                tree.setFather(value.getFather());
            else
                tree.setFather(father);
            if (isAddTier)
                tree.setTier(value.getTier() + 1);
            else
                tree.setTier(value.getTier() - 1);
            treeMapper.updateById(tree);

            //递归调用
            QueryWrapper<Tree> wrapper = new QueryWrapper<>();
            wrapper.eq("father", tree.getId());
            List<Tree> children = treeMapper.selectList(wrapper);
            if (children != null)
                deepUpdateTreeOfTierOrFather(children, isAddTier, 0);
        }
    }

    //递归修改其层数
    public void deepTreeOfTier(List<Tree> list, int tier, int father){
        Tree tree;
        for (Tree value : list) {
            tree = value;
            tree.setId(0);
            tree.setSequence(tier);
            tree.setFather(father);
            treeMapper.insert(tree);
            //递归调用
            QueryWrapper<Tree> wrapper = new QueryWrapper<>();
            wrapper.eq("father", value.getId());
            List<Tree> children = treeMapper.selectList(wrapper);
            if (children != null)
                deepTreeOfTier(children, tier + 1, tree.getId());
        }
    }

}
